package com.anti.modular.sys.dict.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.anti.commom.core.exception.BusinessException;
import com.anti.commom.core.exception.enums.StatusExceptionEnum;
import com.anti.commom.enums.CommonStatusEnum;
import com.anti.core.context.login.LoginContextHolder;
import com.anti.jdbc.DBUtils;
import com.anti.jdbc.support.page.PageParam;
import com.anti.jdbc.support.page.PageResult;
import com.anti.modular.sys.auth.factory.TreeBuildFactory;
import com.anti.modular.sys.dict.entity.SysDictType;
import com.anti.modular.sys.dict.enums.SysDictTypeExceptionEnum;
import com.anti.modular.sys.dict.param.SysDictTypeParam;
import com.anti.modular.sys.dict.result.SysDictTreeNode;
import com.anti.modular.sys.dict.service.SysDictDataService;
import com.anti.modular.sys.dict.service.SysDictTypeService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description TODO
 * @Author anTi
 * @Date 2021-3-5
 */
@Service
public class SysDictTypeServiceImpl implements SysDictTypeService {
    @Resource
    DBUtils dbUtils;

    @Resource
    SysDictDataService sysDictDataService;

    @Override
    public PageResult page(PageParam pageParam, SysDictTypeParam sysDictTypeParam) {

        //构造条件
        StringBuilder sb=new StringBuilder("select * from sys_dict_type where status <> 2");

        ArrayList<Object> params = CollectionUtil.newArrayList();

        if (ObjectUtil.isNotNull(sysDictTypeParam)) {
            //根据字典类型名称模糊查询
            if (ObjectUtil.isNotEmpty(sysDictTypeParam.getName())) {
                sb.append(" and name like ? ");
                params.add("%"+sysDictTypeParam.getName()+"%");
            }

            //根据字典类型编码模糊查询
            if (ObjectUtil.isNotEmpty(sysDictTypeParam.getCode())) {
                sb.append(" and code like ? ");
                params.add("%"+sysDictTypeParam.getCode()+"%");
            }
        }

        sb.append(" order by sort asc ");
        PageResult pageResult = dbUtils.query(pageParam, sb.toString(), params.toArray());
        return pageResult;
    }

    @Override
    public SysDictType detail(SysDictTypeParam sysDictTypeParam) {
        return this.querySysDictType(sysDictTypeParam);

    }

    @Override
    public void add(SysDictTypeParam sysDictTypeParam) {
        //校验参数，检查是否存在重复的编码或者名称，不排除当前添加的这条记录
        checkParam(sysDictTypeParam, false);

        //将dto转为实体
        SysDictType sysDictType = new SysDictType();
        BeanUtil.copyProperties(sysDictTypeParam, sysDictType);

        //设置状态为启用
        sysDictType.setStatus(CommonStatusEnum.ENABLE.getCode());
        sysDictType.setCreateTime(new Date());
        sysDictType.setCreateUser(LoginContextHolder.me().getSysLoginUserId());
        dbUtils.insert(sysDictType);
    }

    @Override
    public void delete(SysDictTypeParam sysDictTypeParam) {
        //根据id查询实体
        SysDictType sysDictType = this.querySysDictType(sysDictTypeParam);

        //逻辑删除，修改状态
        sysDictType.setStatus(CommonStatusEnum.DELETED.getCode());

        //更新实体
        dbUtils.update(sysDictType);

        //级联删除字典值
        sysDictDataService.deleteByTypeId(sysDictType.getId());
    }

    @Override
    public void edit(SysDictTypeParam sysDictTypeParam) {
        //根据id查询实体
        SysDictType sysDictType = this.querySysDictType(sysDictTypeParam);

        //校验参数，检查是否存在重复的编码或者名称，排除当前编辑的这条记录
        checkParam(sysDictTypeParam, true);

        //请求参数转化为实体
        BeanUtil.copyProperties(sysDictTypeParam, sysDictType);

        //不能修改状态，用修改状态接口修改状态
        sysDictType.setStatus(null);
        sysDictType.setUpdateTime(new Date());
        sysDictType.setUpdateUser(LoginContextHolder.me().getSysLoginUserId());
        dbUtils.update(sysDictType);
    }

    @Override
    public void saveChangeStatus(SysDictTypeParam sysDictTypeParam) {
        Long id = sysDictTypeParam.getId();
        Integer status = sysDictTypeParam.getStatus();

        //校验状态在不在枚举值里
        CommonStatusEnum.validateStatus(status);

        //更新枚举，更新只能更新未删除状态的
        String sql="update sys_dict_type set status=? where id =? and status <> 2";
        int i = dbUtils.execSql(sql, status, id);
        if (i==0) {
            throw new BusinessException(StatusExceptionEnum.UPDATE_STATUS_ERROR);
        }
    }

    @Override
    public List<SysDictType> list(SysDictTypeParam sysDictTypeParam) {
        String sql="select * from  sys_dict_type where status=0 and code=?";
        return dbUtils.query(sql,SysDictType.class,sysDictTypeParam.getCode());
    }

    @Override
    public List<SysDictTreeNode> tree() {
        List<SysDictTreeNode> resultList = CollectionUtil.newArrayList();
        String dicTypeSql="select id, 0  pid,  code, name from sys_dict_type where status=0 order by sort";
        List<SysDictTreeNode> sysDictTypeTreeNode = dbUtils.query(dicTypeSql, SysDictTreeNode.class);
        resultList.addAll(sysDictTypeTreeNode);
        String dicDataSql="select id, type_id as  pid,  code,value as name from sys_dict_data where status=0 order by sort\n";
        List<SysDictTreeNode> sysDictDataTreeNode = dbUtils.query(dicDataSql, SysDictTreeNode.class);
        resultList.addAll(sysDictDataTreeNode);
        return new TreeBuildFactory<SysDictTreeNode>().doTreeBuild(resultList);
    }

    @Override
    public List<Dict> dropDown(SysDictTypeParam sysDictTypeParam) {
        String sql="select id from sys_dict_type where status=0 and code=?";
        SysDictType sysDictType = dbUtils.getFirst(sql,SysDictType.class,sysDictTypeParam.getCode());
        if (ObjectUtil.isNull(sysDictType)) {
            throw new BusinessException(SysDictTypeExceptionEnum.DICT_TYPE_NOT_EXIST);
        }
        List<Dict> dictDataList = sysDictDataService.getDictDataListByDictTypeId(sysDictType.getId());
        return dictDataList;
    }

    private void checkParam(SysDictTypeParam sysDictTypeParam, boolean isExcludeSelf) {
        Long id = sysDictTypeParam.getId();
        String name = sysDictTypeParam.getName();
        String code = sysDictTypeParam.getCode();

        //构建带name和code的查询条件
        StringBuilder nameSb=new StringBuilder("select count(*) from sys_dict_type where status <> 2 and name =? ");
        ArrayList<Object> nameParams = CollectionUtil.newArrayList();
        ArrayList<Object> codeParams = CollectionUtil.newArrayList();
        StringBuilder codeSb=new StringBuilder("select count(*) from sys_dict_type where status <> 2 and code =? ");
        nameParams.add(name);
        codeParams.add(code);

        //如果排除自己，则增加查询条件主键id不等于本条id
        if (isExcludeSelf) {
            nameSb.append(" and id <> ?");
            codeSb.append(" and id <> ?");
            nameParams.add(id);
            codeParams.add(id);
        }

        //查询重复记录的数量
        int countByName = dbUtils.getIntValue(nameSb.toString(),nameParams.toArray());
        int countByCode = dbUtils.getIntValue(codeSb.toString(),codeParams.toArray());

        //如果存在重复的记录，抛出异常，直接返回前端
        if (countByName >= 1) {
            throw new BusinessException(SysDictTypeExceptionEnum.DICT_TYPE_NAME_REPEAT);
        }
        if (countByCode >= 1) {
            throw new BusinessException(SysDictTypeExceptionEnum.DICT_TYPE_CODE_REPEAT);
        }
    }

    /**
     * 获取系统字典类型
     */
    private SysDictType querySysDictType(SysDictTypeParam sysDictTypeParam) {
        SysDictType sysDictType = dbUtils.get("select * from sys_dict_type where id =?",SysDictType.class,sysDictTypeParam.getId());
        if (ObjectUtil.isNull(sysDictType)) {
            throw new BusinessException(SysDictTypeExceptionEnum.DICT_TYPE_NOT_EXIST);
        }
        return sysDictType;
    }
}
